<template>
  <el-form>
    <el-form-item label="SPU名称">
      <el-input
        v-model="spuParams.spuName"
        placeholder="请输入SPU名称"
        size="normal"
        clearable
      ></el-input>
    </el-form-item>
    <el-form-item label="SPU品牌">
      <el-select v-model="spuParams.tmId" placeholder="请选择" clearable>
        <el-option
          v-for="(trademark, index) in allTrademarkData"
          :key="trademark.id"
          :label="trademark.tmName"
          :value="trademark.id"
        ></el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="SPU描述">
      <el-input
        v-model="spuParams.description"
        placeholder="请输入SPU描述"
        size="normal"
        type="textarea"
        clearable
      ></el-input>
    </el-form-item>
    <el-form-item label="SPU图片" size="normal">
      <el-upload
        v-model:file-list="imgListData"
        action="/api/admin/product/fileUpload"
        list-type="picture-card"
        :on-preview="handlePictureCardPreview"
        :on-remove="handleRemove"
      >
        <el-icon><Plus /></el-icon>
      </el-upload>

      <el-dialog v-model="dialogVisible">
        <img w-full :src="dialogImageUrl" alt="Preview Image" />
      </el-dialog>
    </el-form-item>

    <el-form-item label="销售属性">
      <el-select
        :placeholder="
          unSelectSalesAttr.length > 0
            ? `还有${unSelectSalesAttr.length}个属性未选择`
            : '已经没有了'
        "
        clearable
        v-model="unSelectAttrIdAndName"
      >
        <el-option
          v-for="(unSelectAttr, index) in unSelectSalesAttr"
          :key="unSelectAttr.id"
          :label="unSelectAttr.name"
          :value="`${unSelectAttr.id}:${unSelectAttr.name}`"
        ></el-option>
      </el-select>
      <el-button
        type="primary"
        size="default"
        :icon="Plus"
        style="margin-left: 10px"
        :disabled="!unSelectAttrIdAndName"
        @click="addSalesAttr"
        >添加销售属性</el-button
      >
    </el-form-item>
    <el-table border stripe style="margin: 10px 0" :data="hadSalesData">
      <el-table-column label="序号" type="index" align="center" width="80">
      </el-table-column>
      <el-table-column label="属性名" prop="saleAttrName" width="120px">
      </el-table-column>
      <el-table-column label="属性值名称列表">
        <template #="{ row, $index }">
          <el-tag
            type="success"
            size="small"
            closable
            style="margin-right: 5px"
            v-for="(attrVal, index) in row.spuSaleAttrValueList"
            :key="attrVal.id"
            @close="row.spuSaleAttrValueList.splice(index, 1)"
            >{{ attrVal.saleAttrValueName }}</el-tag
          >
          <!-- 编辑模式 失焦切换为查看模式 -->
          <el-input
            v-if="row.flag"
            size="small"
            style="width: 90px"
            placeholder="请输入属性值"
            @blur="toLook(row, $index)"
            v-model="row.inputValue"
            :ref="(vc) => (inputArr[$index] = vc)"
          ></el-input>
          <!-- 查看模式  点击加号切换为编辑模式 -->
          <el-button
            v-else
            size="small"
            :icon="Plus"
            @click="toEdit(row, $index)"
          ></el-button>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="120px">
        <template #="{ row, $index }">
          <el-button
            type="danger"
            size="small"
            :icon="Delete"
            @click="hadSalesData.splice($index, 1)"
          ></el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-button type="primary" size="default" @click="save">保存</el-button>
    <el-button @click="cancel">取消</el-button>
  </el-form>
</template>

<script setup lang="ts">
// 引入icon图标
import {
  Check,
  Delete,
  Edit,
  Message,
  Search,
  Star,
  //加号
  Plus,
  InfoFilled,
} from "@element-plus/icons-vue";
import { ref, computed, nextTick } from "vue";
import type { UploadProps, UploadUserFile } from "element-plus";
import { ElMessage } from "element-plus";
import {
  reqAddOrUpdateSpuAttr,
  reqAllTrademark,
  reqBaseSalesAttr,
  reqHadSalesAttr,
  reqImgList,
} from "@/api/product/spu/spu";

// 存储四个请求服务器返回的数据
// 品牌数据
let allTrademarkData = ref([]);
// 照片墙数据
let imgListData = ref([]);
// 销售属性数据
let baseSalesData = ref([]);
// 已有销售属性数据
let hadSalesData = ref([]);

// 定义服务器返回的数据
let spuParams = ref<any>({});

// 定义还未选择的销售属性的id和name
let unSelectAttrIdAndName = ref("");

let inputArr = ref([]);

//照片墙相关的代码
//存储预览图片地址
const dialogImageUrl = ref("");
//控制对话框显示与隐藏
const dialogVisible = ref(false);

//删除图片的回调
const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
  console.log(uploadFile, uploadFiles);
};
//预览的回调
const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url!;
  dialogVisible.value = true;
};

// 触发自定义事件
let emit = defineEmits(["changeScene"]);

// 在子组件上定义一个方法,让父组件之后可以调用
const initSpuData = async (row) => {
  // console.log(row)
  spuParams.value = row;
  // 该页面我们练习先做修改按钮,即父组件点击修改按钮,触发子组件的这个方法,发送四个请求
  // 因为点击的是父组件的修改按钮,所以此处的row指的是spu列表的每一个spu对象
  // 获取全部品牌的请求
  let spu1 = reqAllTrademark();
  // 获取照片墙的请求
  let spu2 = reqImgList(row.id);
  // 获取spu对象的全部销售属性
  let spu3 = reqBaseSalesAttr();
  // 获取当前spu对象已有的销售属性
  let spu4 = reqHadSalesAttr(row.id);
  // 使用async和await将异步变为同步,即等四个请求的数据都返回之后再执行之后的代码
  // 结合promise的all方法一起使用
  let result = await Promise.all([spu1, spu2, spu3, spu4]);
  // 存数据
  // 存储品牌数据
  allTrademarkData.value = result[0];
  // 存储照片墙数据
  imgListData.value = result[1].map((item) => {
    return {
      name: item.imgName,
      url: item.imgUrl,
    };
  });
  // 存储销售属性数据
  baseSalesData.value = result[2];
  // 存储已有销售属性数据
  hadSalesData.value = result[3];
  console.log(result);
};

// 在子组件上定义一个方法,让父组件可以调用
const initAddSpu = async (c3Id: string | number) => {
  // 添加SPU追加三级分类ID
  spuParams.value.category3Id = c3Id;
  // 获取全部品牌的请求
  let spu1 = reqAllTrademark();
  // 获取spu对象的全部销售属性
  let spu2 = reqBaseSalesAttr();
  // 结合promise的all方法一起使用
  let result = await Promise.all([spu1, spu2]);
  // 存储品牌数据
  allTrademarkData.value = result[0];
  // 存储销售属性数据
  baseSalesData.value = result[1];
};

// 记得暴露子组件上的该方法,让父组件可以调用该方法
defineExpose({
  initSpuData,
  initAddSpu,
});

// 计算剩余销售属性的个数
let unSelectSalesAttr = computed(() => {
  // 过滤出没有的销售属性,filter的返回值是布尔值,为真则过滤出来,为假则不要
  let result = baseSalesData.value.filter((item) => {
    return hadSalesData.value.every((item1) => {
      return item.name != item1.saleAttrName;
    });
  });
  return result;
});

// 点击添加销售属性按钮的回调
const addSalesAttr = () => {
  // 整理数据,将id和name的分开,直接解构
  let [baseSaleAttrId, saleAttrName] = unSelectAttrIdAndName.value.split(":");
  // 定义新添加数据的类型
  let newSalesAttr = { baseSaleAttrId, saleAttrName, spuSaleAttrValueList: [] };
  // 向数组中添加销售属性对象
  hadSalesData.value.push(newSalesAttr);
  // 清空输入框的数据
  unSelectAttrIdAndName.value = "";
};

// 点击添加销售属性值按钮切换为编辑模式
const toEdit = (row, $index) => {
  // row是当前每一个销售属性对象,给其的销售属性值添加一个flag属性,实现一对一控制
  row.flag = true;
  row.inputValue = "";
  // 切换到编辑模式时聚焦,整体思路就是拿到el-input的实例对象,这样才可以绑定focus方法
  // 记得使用nextTick拿到最新页面
  nextTick(() => {
    inputArr.value[$index].focus();
  });
};

// 失去焦点切换为查看模式,并向数组中添加属性值
const toLook = (row) => {
  // 解决两个小问题:一:文本框内容不能为空
  if (row.inputValue == "") {
    // 提示信息
    ElMessage({
      type: "error",
      message: "属性值不能为空",
    });
    return;
  }

  // 二:属性值不能重复  使用数组的find方法,该方法的返回值为布尔值
  let repeated = row.spuSaleAttrValueList.find((item) => {
    return row.inputValue == item.saleAttrValueName;
  });
  if (repeated) {
    // 提示信息
    ElMessage({
      type: "error",
      message: "属性值不能重复",
    });
    // 清空输入框的数据
    row.inputValue = "";
    // 直接返回,代码不再往下执行
    return;
  }

  row.flag = false;
  // 整理数据
  let newSalesAttrValue = {
    baseSaleAttrId: row.baseSaleAttrId,
    saleAttrValueName: row.inputValue,
  };
  // 向数组中添加属性值
  row.spuSaleAttrValueList.push(newSalesAttrValue);
  // 清空文本框中的数据
  row.inputValue = "";
};

// 点击保存按钮的回调
const save = async () => {
  // 整理数据:还需整理的数据是 => 照片墙的数据 | 销售属性的数据
  // 照片墙数据:首先将名字改回来,即 name => imgName url => imgUrl
  spuParams.value.spuImageList = imgListData.value.map((item) => {
    return {
      imgName: item.name,
      imgUrl: (item.response && item.response.data) || item.url,
    };
  });
  // 销售属性数据
  spuParams.value.spuSaleAttrList = hadSalesData.value;
  // 发请求
  try {
    await reqAddOrUpdateSpuAttr(spuParams.value);
    ElMessage({
      type: "success",
      message: spuParams.value.id ? "修改成功" : "添加成功",
    });
    emit("changeScene", {
      scenes: 0,
      whichOne: spuParams.value.id ? "update" : "add",
    });
    // 清空数据
    resetData()
  } catch (error) {
    ElMessage({
      type: "error",
      message: spuParams.value.id ? "修改失败" : "添加失败",
    });
  }
};

// 定义清空数据的方法
const resetData = () => {
  spuParams.value = {};
  imgListData.value = [];
  baseSalesData.value = [];
};

// 点击取消按钮的回调
const cancel = () => {
  emit("changeScene", {
    scenes: 0,
    whichOne: spuParams.value.id ? "update" : "add",
  });
  // 调用清空数据的函数
  resetData();
};
</script>

<style scoped>
</style>